# -*- coding: utf-8 -*-
__author__ = 'HaoGe'
from django.views.generic import ListView, View, DetailView, TemplateView
from django.http import JsonResponse, QueryDict
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render_to_response,HttpResponse,render
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from resources.models import NewServer,ServerUser,ServerGroup
from resources.forms import CreateServerAutoForm, CreateServerForm
from devops.views import AddMysqlJob,ModifyJob,StopJob,ReStart,ReMove,AddOracleJob
from products.models import Product
from devops.ansible_api import ansible_setup,ansible_authorized_key
from confs.views import get_pagerange
from django.core import serializers
from confs.Log import logger
import sys
import pexpect
import importlib
import pathlib
importlib.reload(sys)
import json
import os
import xlrd
import csv
import base64

def putPublicKey(publicKey,user,server,port,password):
    ret = {}
    try:
        print ("/usr/bin/ssh-copy-id -p %s -i '%s' %s@%s" %(port,publicKey,user,server))
        child = pexpect.spawn("/usr/bin/ssh-copy-id -p %s -i %s %s@%s" %(port,publicKey,user,server))
        index = child.expect(["yes/no","password","exist",pexpect.exceptions.EOF, pexpect.TIMEOUT])
        if index != 0 and index != 1:
            print ("未向%s上传公钥匙"%(server))
            child.close(force=True)
        else:
        #if 1 == 1:
            print ("开始向%s上传公钥"%(server))
            child.sendline("yes")
            child.expect("password")
            child.sendline("%s"%password)
            child.expect("added")
            print ("已向%s上传公钥"%(server))

        ret['status'] = 0
        ret['msg'] = 'good'

    except Exception as e:
        logger.info(e)
        ret['status'] = 1
        ret['msg'] = str(e)

    return ret


# 服务器展示
class ServerListView(LoginRequiredMixin, ListView):
    template_name = 'servers/server_list.html'
    model = NewServer
    paginate_by = 10
    ordering = 'id'

    def get_context_data(self, **kwargs):
        context = super(ServerListView, self).get_context_data(**kwargs)
        context['os_list'] = NewServer.os_status_list
        context['system_list'] = NewServer.system_status_list
        context['systemuser_list'] = ServerUser.objects.all()
        context['servergroups'] = ServerGroup.objects.all()
        context['page_range'] = get_pagerange(context['page_obj'])
        return context

class ServerCreateView(LoginRequiredMixin, View):

    def post(self, request):
        ret = {'status': 0}
        hostname = request.POST.get('hostname')
        ip_inner = request.POST.get('ip_inner')
        port = request.POST.get('port')
        serveruser_id = request.POST.get('serveruser_id','')
        servergroup_id = request.POST.get('servergroup_id', '')
        try:
            servergroup = ServerGroup.objects.get(pk=servergroup_id)
        except:
            ret['status'] = 1
            ret['msg'] = '请先添加资产组'
            return JsonResponse(ret)

        try:
            serveruser = ServerUser.objects.get(pk=serveruser_id)
            hoc_password = serveruser.password
            hoc_username = serveruser.username
            hoc_privatekey = serveruser.privatekey
            hoc_pubkey = serveruser.pubkey
        except:
            ret['status'] = 1
            ret['msg'] = '请先添加资产用户'
            return JsonResponse(ret)
        os_status = request.POST.get('os_status')
        system_status = request.POST.get('system_status')

        #第一次创建主机使用密码登录
        #if len(hoc_privatekey) > 10:
        #    assets = [
        #        {
        #            "hostname": hostname,
        #            "ip": ip_inner,
        #            "port": port,
        #            "username": hoc_username,
        #            "private_key_file": hoc_privatekey
        #        }]
        #else:

        #使用密码登录验证创建主机
        assets = [
            {
                "hostname": hostname,
                "ip": ip_inner,
                "port": port,
                "username": hoc_username,
                "password": hoc_password,
            }]
        #获取资产信息
        result = ansible_setup(assets)
        #logger.info(result)

        # 推送公钥到服务器

        if not  (hoc_privatekey == '' or hoc_pubkey == ''):
            tmp_path = '/tmp/fsr'
            if not os.path.exists(tmp_path):
                os.makedirs(tmp_path)
            publicKey = '%s/id_rsa.pub' % (tmp_path)
            with open(publicKey, 'w') as f:
                f.write(hoc_pubkey)
            # 创建空私钥文件
            id_rsa_file = '%s/id_rsa' % (tmp_path)
            pathlib.Path(id_rsa_file).touch()
            # 推送公钥
            pstate = putPublicKey(publicKey, hoc_username, ip_inner, port, hoc_password)
            if pstate['status'] == 1:
                ret['status'] = 1
                ret['msg'] = pstate['msg']
                return JsonResponse(ret)


        if result['contacted'] == {}:
            scan_status = 0
            ret['status'] = 1
            ret['msg'] = str(result)
        else:
            scan_status = 1
            mem_info = result['contacted'][hostname][0]['ansible_facts']['ansible_memtotal_mb']
            cpu_count = result['contacted'][hostname][0]['ansible_facts']['ansible_processor_count']
            cpu_info = result['contacted'][hostname][0]['ansible_facts']['ansible_kernel']
            uuid = result['contacted'][hostname][0]['ansible_facts']['ansible_product_uuid']
            os_system_num = result['contacted'][hostname][0]['ansible_facts']['ansible_architecture'].split('_')[1]
            ret['msg'] = '自动推送完成'
            NewServer.objects.create(hostname=hostname,ip_inner=ip_inner,port=port,os_status=os_status,
            system_status=system_status,scan_status=scan_status,mem_info=mem_info,cpu_count=cpu_count,
            cpu_info=cpu_info,uuid=uuid,os_system_num=os_system_num,server_user=serveruser,server_group=servergroup)

        return JsonResponse(ret)

class ServerAddServerView(LoginRequiredMixin, View):

    template_name = 'servers/add_server.html'

    def get(self, request):

        os_list = NewServer.os_status_list
        system_list = NewServer.system_status_list
        systemuser_list = json.loads(serializers.serialize("json",ServerUser.objects.all().order_by("-id")[::1]))
        servergroups = json.loads(serializers.serialize("json",ServerGroup.objects.all().order_by("-id")[::1]))

        jsondata = {"os_list":os_list,"system_list":system_list,"systemuser_list":systemuser_list,"servergroups":servergroups}
        return JsonResponse(jsondata)

class ServerAPIJsonView(LoginRequiredMixin, View):

    template_name = 'servers/server_edit.html'

    def get(self, request):
        jsondata = {
            "code": 0,
            "msg": "",
            "count": 10,
            "data": [
            ]
        }
        servers = NewServer.objects.all()
        for s in servers:
            m = {"id":s.id,"hostname":s.hostname,"ip_inner":s.ip_inner,"port":s.port,"server_group":s.server_group.name,
                 "system_status":s.system_status,"scan_status":s.scan_status,"cpu_count":s.cpu_count,"cpu_info":s.cpu_info,
                 "mem_info":s.mem_info,"create_date":s.create_date}
            jsondata["data"].append(m)

        return JsonResponse(jsondata)

class ServerEditView(LoginRequiredMixin, View):

    template_name = 'servers/server_edit.html'

    def get(self, request):
        id = request.GET.get('id')
        server = NewServer.objects.get(id=id)
        hostname = server.hostname
        ip_inner = server.ip_inner
        port = server.port
        os_status = server.os_status
        system_status = server.system_status
        #servergroup_list = ServerGroup.objects.all()
        servergroup = server.server_group
        serveruser = server.server_user
        #system_status_list = NewServer.system_status_list
        system_status = server.system_status

        os_list = NewServer.os_status_list
        system_list = NewServer.system_status_list
        systemuser_list = json.loads(serializers.serialize("json", ServerUser.objects.all().order_by("-id")[::1]))
        servergroups = json.loads(serializers.serialize("json", ServerGroup.objects.all().order_by("-id")[::1]))
        servergroup = {"id":servergroup.id,"name":servergroup.name}
        serveruser = {"id": serveruser.id, "name": serveruser.name}

        jsondata = {"id":id,"os_list": os_list, "system_list": system_list, "systemuser_list": systemuser_list,
                    "servergroups": servergroups,"hostname":hostname,"ip_inner":ip_inner,"port":port,
                    "servergroup":servergroup,"system_status":system_status,"serveruser":serveruser,
                    "os_status":os_status,"system_status":system_status}
        return JsonResponse(jsondata)
    

    def post(self, request):
        ret = {'status': 0}
        id = request.POST.get('id')
        hostname = request.POST.get('hostname')
        ip_inner = request.POST.get('ip_inner')
        port = request.POST.get('port')
        servergroup_id = request.POST.get('servergroup_id')
        system_status = request.POST.get('system_status')

        server = NewServer.objects.get(id=id)
        sg = ServerGroup.objects.get(id=servergroup_id)
        server.hostname = hostname
        server.ip_inner = ip_inner
        server.port = port
        server.server_group = sg
        server.system_status = system_status
        server.save()

        ret['msg'] = '自动推送完成'
        return JsonResponse(ret)

# 接收服务器数据接口
class ServerDataApiView(View):

    @csrf_exempt
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        ret = {'status': 0}
        data = request.body
        data_dict = json.loads(data)
        server_form = CreateServerForm(data_dict)
        print(data_dict)
        if server_form.is_valid():
            try:
                server = Server(**server_form.cleaned_data)
                server.server_auto_id = data_dict['server_auto_id']
                server.scan_status = 1
                server.save()

                for key, value in data_dict['disk_info'].items():
                    Disk.objects.create(name=key, size=value, server=server)

                for key, value in data_dict['ip_info'].items():
                    Ip.objects.create(name=key, ip_address=value, server=server)
            except:
                ret['status'] = 1
                ret['msg'] = '添加服务器失败'
        return JsonResponse(ret)

    def put(self, request):
        ret = {'status': 0}
        data = request.body
        data_dict = json.loads(data)
        server_auto_id = data_dict['server_auto_id']
        server_id = ServerAuto.objects.get(pk=server_auto_id).server.id
        print(server_id)
        server_form = CreateServerForm(data_dict)
        print('put', data_dict)
        if server_form.is_valid():
            try:
                server = Server.objects.get(pk=server_id)
                server.hostname = server_form.cleaned_data['hostname']
                server.cpu_info = server_form.cleaned_data['cpu_info']
                server.cpu_count = server_form.cleaned_data['cpu_count']
                server.mem_info = server_form.cleaned_data['mem_info']
                server.os_system = server_form.cleaned_data['os_system']
                server.os_system_num = server_form.cleaned_data['os_system_num']
                server.save()

                server.disk_set.all().delete()
                server.ip_set.all().delete()

                for key, value in data_dict['disk_info'].items():
                    Disk.objects.create(name=key, size=value, server=server)

                for key, value in data_dict['ip_info'].items():
                    Ip.objects.create(name=key, ip_address=value, server=server)

            except:
                ret['status'] = 1
                ret['msg'] = '添加服务器失败'
        return JsonResponse(ret)


# 服务器详情展示
class ServerDetailView(LoginRequiredMixin, DetailView):
    template_name = 'servers/server_detail.html'
    model = NewServer

    def get_context_data(self, **kwargs):
        context = super(ServerDetailView, self).get_context_data(**kwargs)
        context['idc_list'] = Idc.objects.all()
        return context


# 修改服务器的IDC机房归属
class ServerModifyIdcView(LoginRequiredMixin, View):

    def post(self, request):
        print(request.POST)
        ret = {"status": 0, 'msg': '修改成功'}
        idc_id = request.POST.get('idc_id')
        server_id = request.POST.get('server_id')
        try:
            server = Server.objects.get(pk=server_id)
            if idc_id:
                try:
                    server.idcs_id = idc_id
                    server.save()
                except Exception:
                    ret['status'] = 1
                    ret['msg'] = '其他错误，修改失败请联系管理员'
            else:
                server.idcs = None
        except Server.DoesNotExist:
            ret['status'] = 1
            ret['msg'] = '没有此服务器，修改失败'
        except Exception:
            ret['status'] = 1
            ret['msg'] = '其他错误，请联系系统管理员'

        return JsonResponse(ret)


# 删除服务器
class ServerDeleteView(LoginRequiredMixin, View):

    def post(self, request):
        ret = {'status': 0}
        server_id = request.POST.get('server_id')
        print ('server_id is ',server_id)
        #定时任务删除
        try:
            ReMove(server_id)
        except Exception as e:
            print (e)

        try:
            server = NewServer.objects.get(id=server_id)
            server.delete()
            ret['msg'] = '删除服务器成功'
        except NewServer.DoesNotExist:
            ret['status'] = 1
            ret['msg'] = '此服务器不存在，删除失败'
        except Exception:
            ret['status'] = 1
            ret['msg'] = '其他错误，请联系系统管理员'

        return JsonResponse(ret)


# 刷新探测服务器
class ServerFlushView(LoginRequiredMixin, View):

    def post(self, request):
        ret = {'status': 0}
        ret['msg'] = '刷新成功'
        server_id = request.POST.get('server_id')
        return JsonResponse(ret)


# 业务线获取主机信息
class ServerGetListView(LoginRequiredMixin, View):

    def get(self, request):
        ret = {'status': 0}
        product_id = request.GET.get('id')
        try:
            product = Product.objects.get(pk=product_id)
            ret['data'] = list(
                product.product_host.all().values('id', 'hostname', 'server_auto__ip_inner', 'scan_status',
                                                  'idcs__name_cn'))
        except Exception:
            ret['status'] = 1
            ret['msg'] = '查询失败'
        return JsonResponse(ret)


# 设置业务线
class ServerSetProduct(LoginRequiredMixin, TemplateView):
    template_name = 'servers/server_set_product.html'

    def get_context_data(self, **kwargs):
        context = super(ServerSetProduct, self).get_context_data(**kwargs)
        server_id = self.request.GET.get('id')
        server = Server.objects.get(pk=server_id)
        context['server'] = server
        context['product_one_list'] = Product.objects.filter(level=1)
        context['product_two_list'] = Product.objects.filter(level=2)
        context['product_host_list'] = Product.objects.filter(level=3)
        return context

    def post(self, request):
        ret = {'status': 0}
        server_id = request.POST.get('server_id')
        product_one = request.POST.get('product_one')
        product_two = request.POST.get('product_two')
        product_host = request.POST.get('product_host')
        if product_one and product_two and product_host:
            try:
                Server.objects.filter(pk=server_id).update(
                    product_one=product_one,
                    product_two=product_two,
                    product_host=product_host,
                )
                ret['msg'] = '设置成功'
            except Exception:
                ret['status'] = 1
                ret['msg'] = '设置失败'
        else:
            ret['status'] = 1
            ret['msg'] = '设置失败'
        return JsonResponse(ret)

# 业务线获取主机信息
class ServerLoadView(LoginRequiredMixin, TemplateView):
    template_name = 'servers/serverload.html'

    def get_context_data(self, **kwargs):
        context = super(ServerLoadView, self).get_context_data(**kwargs)
        return context

    def post(self, request):
        content = request.FILES.get("upload", None)
        if not content:
            return HttpResponse("没有上传内容")
        position = os.path.join('/tmp/', content.name)
        # 获取上传文件的文件名，并将其存储到指定位置
        storage = open(position, 'wb+')  # 打开存储文件
        for chunk in content.chunks():  # 分块写入文件
            storage.write(chunk)
        storage.close()  # 写入完成后关闭文件

        #导入csv文件
        try:
            f = open(position,encoding='gbk')
        except:
            f = open(position, encoding='utf-8')

        reader = csv.reader(f)
        num = 1
        for i in reader:
            if num == 1:
                num += 1
                continue

            hostname = i[0]
            ip_inner = i[1]
            port = i[2]
            server_group = i[3]
            server_user = i[4]
            print (hostname,ip_inner,port,server_group,server_user)

            serveruser = ServerUser.objects.get(name=server_user)
            hoc_password = serveruser.password
            hoc_username = serveruser.username
            hoc_privatekey = serveruser.privatekey
            os_status = 0
            system_status = 0

            if len(hoc_privatekey) > 10:
                assets = [
                    {
                        "hostname": hostname,
                        "ip": ip_inner,
                        "port": port,
                        "username": hoc_username,
                        "private_key_file": hoc_privatekey
                    }]
            else:
                assets = [
                    {
                        "hostname": hostname,
                        "ip": ip_inner,
                        "port": port,
                        "username": hoc_username,
                        "password": hoc_password,
                    }]

            result = ansible_setup(assets)

            if result['contacted'] == {}:
                scan_status = 0
                msg = '自动推送失败'
                return HttpResponse(msg)
            else:
                scan_status = 1
                mem_info = result['contacted'][hostname][0]['ansible_facts']['ansible_memtotal_mb']
                cpu_count = result['contacted'][hostname][0]['ansible_facts']['ansible_processor_count']
                cpu_info = result['contacted'][hostname][0]['ansible_facts']['ansible_kernel']
                uuid = result['contacted'][hostname][0]['ansible_facts']['ansible_product_uuid']
                os_system_num = \
                result['contacted'][hostname][0]['ansible_facts']['ansible_architecture'].split('_')[1]

                #主机组
                server_group = ServerGroup.objects.get(name=server_group)

                NewServer.objects.create(hostname=hostname, ip_inner=ip_inner, port=port, os_status=os_status,
                                         system_status=system_status, scan_status=scan_status, mem_info=mem_info,
                                         cpu_count=cpu_count,
                                         cpu_info=cpu_info, uuid=uuid, os_system_num=os_system_num,
                                         server_user=serveruser,server_group=server_group)
                num += 1

        #return HttpResponse('上传成功')	  #返回客户端信息
        return HttpResponseRedirect('/resources/servers/list/')


class HostConnectView(LoginRequiredMixin, TemplateView):

    def post(self,request):
        id = request.POST.get('id')
        s = NewServer.objects.get(id=id)
        ret = {}
        host = s.ip_inner
        port = s.port
        serveruser = s.server_user
        #password = base64.b64encode(serveruser.password.encode('utf-8'))
        password = serveruser.password
        user = serveruser.username
        ssh_key = serveruser.privatekey
        auth = 'inlineRadio2'

        ret['host'] = host
        ret['port'] = port
        ret['password'] = password
        ret['user'] = user
        ret['ssh_key'] = ssh_key
        ret['auth'] = auth
        #print (ret)
        return JsonResponse(ret)
        #return HttpResponse(ret)

